package com.wudeyong;

import java.util.Scanner;

/**
 * Author :wudeyong
 * Date 2017/6/14
 * For More Information,Please Visit https://wudeyong.com
 * PageRank算法简单实现--参照大数据实时分析教科书
 */
public class PageRank {
    private int n;
    private double data[][];
//  误差大小为0.001
    private final static double EPUS=0.001;

    public static void main(String []args){
        //输入转移矩阵
        PageRank pageRank=new PageRank();
        pageRank.input();
        System.out.println("采用抽税法的结果为：");
        double result[]=pageRank.calculateByTax();
        pageRank.display(result);
        System.out.println("采用主题法的结果为：");
        double result1[]=pageRank.calculateByTheme();
        pageRank.display(result1);
    }

    public void input(){
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入N：");
        n= Integer.parseInt(scanner.nextLine());
        data=new double[n][n];
        String tmp[];
        for(int i=0;i<n;i++){
            System.out.println("请输入第"+(i+1)+"行数据,以空格分开：");
                tmp=scanner.nextLine().split(" ");
                for(int j=0;j<tmp.length;j++){
                    data[i][j]=Double.parseDouble(tmp[j]);
            }
        }
    }

//抽税法
    public double[] calculateByTax(){
//        初始化向量分布值
        double v[]=new double[n];
//        beta值为0.8
        double beta=0.8d;
        System.out.println("beta的值为"+beta);
        for(int i=0;i<n;i++)
            v[i]=1.0d/n;
        double surplus=0.0d;
//
        do{
            double v1[]=new double[n];
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++)
                    v1[i]=v1[i]+data[i][j]*beta*v[j];
                v1[i]=v1[i]+(1-beta)/n;
            }
            double tmp=0.0d;
            for(int i=0;i<n;i++){
                tmp=tmp+(v1[i]-v[i])*(v1[i]-v[i]);
            }
            surplus=Math.sqrt(tmp);
            v=v1;
        }while(surplus>EPUS);
        return v;
    }
//主题法
    public double[] calculateByTheme(){
//        初始化向量分布值
        double v[]=new double[n];
//        生成随机beta值
        double beta=0.8d;
        double es[]={1,0,1,0,0,0};

        int s=2;
        for(int i=0;i<n;i++)
            v[i]=1.0d/n;
//      阈值
        double surplus=0.0d;
//
        do{
            double v1[]=new double[n];
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++)
                    v1[i]=v1[i]+data[i][j]*beta*v[j];
                v1[i]=v1[i]+(1-beta)*es[i]/s;
            }
            double tmp=0.0d;
            for(int i=0;i<n;i++){
                tmp=tmp+(v1[i]-v[i])*(v1[i]-v[i]);
            }
            surplus=Math.sqrt(tmp);
            v=v1;
        }while(surplus>EPUS);
        return v;
    }

    public void display(double result[]){
        for(int i=0;i<result.length;i++){
            System.out.print("节点"+(i+1)+"的概率为"+result[i]+"\t");
        }
        System.out.println();
    }
}
